﻿
#region Usings
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading.Tasks;
using System.Collections;
using System.Threading;
using System.Windows.Threading;
using System.Windows.Controls.Primitives;
using System.IO;
using System.Windows.Markup;
using System.Reactive;
using System.Reactive.Linq;
using System.Collections.ObjectModel;
using System.Globalization;
using System.ComponentModel;
using Microsoft.Windows.Themes;
#endregion

namespace FasterWPF
{
    public static class ComboBoxExt
    {
        private static bool IsTypeAheadButCannotSelectOrCopyText(this ComboBox cmbx)
        {
            return (cmbx.IsTextSearchEnabled == true && cmbx.IsEditable == false && cmbx.IsReadOnly == true);
        }

        public static void ApplyComboBoxStrategy(this ComboBox cmbx, string widthOrArrowMargin, string toggleButtonBackground, string toggleButtonBorderBrush, bool roundedCorners, string mouseOverHighlightColor, string mouseOverBorderColor, string pressedColor, string pressedBorderColor)
        {
            if(IsTypeAheadButCannotSelectOrCopyText(cmbx))
            {
                cmbx.ApplyTemplate();

                Grid tgb = (Grid)cmbx.Template.FindName("MainGrid", cmbx);

                ToggleButton x = (ToggleButton)tgb.Children[1];

                string xaml = "<ControlTemplate TargetType=\"{x:Type ToggleButton}\"><theme:ButtonChrome Name=\"Chrome\"   Background=\"" + toggleButtonBackground + "\" BorderBrush=\"" + toggleButtonBorderBrush + "\" RenderMouseOver=\"{TemplateBinding IsMouseOver}\" RenderPressed=\"{TemplateBinding IsPressed}\" RoundCorners=\"" + ((roundedCorners) ? "true" : "false") + "\" SnapsToDevicePixels=\"true\"><Path Name=\"Arrow\" Margin=\"" + widthOrArrowMargin + ",1,0,0\" Fill=\"Black\" Data=\"M 1,1.5 L 4.5,5 L 8,1.5\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\"/></theme:ButtonChrome><ControlTemplate.Triggers><Trigger Property=\"IsMouseOver\" Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderMouseOver\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + mouseOverBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + mouseOverHighlightColor + "\"/></Trigger><Trigger Property=\"IsChecked\" Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderPressed\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + pressedBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + pressedColor + "\"/></Trigger><Trigger Property=\"IsEnabled\" Value=\"false\"><Setter TargetName=\"Arrow\" Property=\"Fill\" Value=\"#AFAFAF\"/></Trigger><Trigger Property=\"IsPressed\"        Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderPressed\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + pressedBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + pressedColor + "\"/></Trigger></ControlTemplate.Triggers></ControlTemplate>";

                MemoryStream sr = new MemoryStream(Encoding.ASCII.GetBytes(xaml));
                ParserContext pc = new ParserContext();
                pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
                pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
                pc.XmlnsDictionary.Add("theme", "clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero");
                var btnTemplate = (ControlTemplate)XamlReader.Load(sr, pc);
                x.Template = btnTemplate;
            }
            else
            {
                cmbx.ApplyTemplate();

                Grid tgb = (Grid)cmbx.Template.FindName("Placement", cmbx);

                ToggleButton x = (ToggleButton)tgb.Children[3];

                string xaml = "<ControlTemplate TargetType=\"{x:Type ToggleButton}\"><theme:ButtonChrome Name=\"Chrome\"  Width=\"" + widthOrArrowMargin + "\" Background=\"" + toggleButtonBackground + "\" BorderBrush=\"" + toggleButtonBorderBrush + "\" RenderMouseOver=\"{TemplateBinding IsMouseOver}\" RenderPressed=\"{TemplateBinding IsPressed}\" RoundCorners=\"" + ((roundedCorners) ? "true" : "false") + "\" SnapsToDevicePixels=\"true\"><Path Name=\"Arrow\" Margin=\"0,1,0,0\" Fill=\"Black\" Data=\"M 1,1.5 L 4.5,5 L 8,1.5\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\"/></theme:ButtonChrome><ControlTemplate.Triggers><Trigger Property=\"IsMouseOver\" Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderMouseOver\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + mouseOverBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + mouseOverHighlightColor + "\"/></Trigger><Trigger Property=\"IsChecked\" Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderPressed\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + pressedBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + pressedColor + "\"/></Trigger><Trigger Property=\"IsEnabled\" Value=\"false\"><Setter TargetName=\"Arrow\" Property=\"Fill\" Value=\"#AFAFAF\"/></Trigger><Trigger Property=\"IsPressed\"        Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderPressed\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + pressedBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + pressedColor + "\"/></Trigger></ControlTemplate.Triggers></ControlTemplate>";
            
                MemoryStream sr = new MemoryStream(Encoding.ASCII.GetBytes(xaml));
                ParserContext pc = new ParserContext();
                pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
                pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
                pc.XmlnsDictionary.Add("theme", "clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero");
                var btnTemplate = (ControlTemplate)XamlReader.Load(sr, pc);
                x.Template = btnTemplate;
            }
        }

        public static void ApplyComboBoxStrategy(this ComboBox cmbx, string widthOrArrowMargin, string toggleButtonBackground, string toggleButtonBorderBrush, bool roundedCorners, string mouseOverHighlightColor, string mouseOverBorderColor, string pressedColor, string pressedBorderColor, string arrowFillColor, string arrowGeometryPath, string mouseOverArrowColor, string pressedArrowColor, string arrowDisabledColor)
        {
            if (IsTypeAheadButCannotSelectOrCopyText(cmbx))
            {
                cmbx.ApplyTemplate();

                Grid tgb = (Grid)cmbx.Template.FindName("MainGrid", cmbx);

                ToggleButton x = (ToggleButton)tgb.Children[1];

                string xaml = "<ControlTemplate TargetType=\"{x:Type ToggleButton}\"><theme:ButtonChrome Name=\"Chrome\"   Background=\"" + toggleButtonBackground + "\" BorderBrush=\"" + toggleButtonBorderBrush + "\" RenderMouseOver=\"{TemplateBinding IsMouseOver}\" RenderPressed=\"{TemplateBinding IsPressed}\" RoundCorners=\"" + ((roundedCorners) ? "true" : "false") + "\" SnapsToDevicePixels=\"true\"><Path Name=\"Arrow\" Margin=\"" + widthOrArrowMargin + ",1,0,0\" Fill=\"" + arrowFillColor + "\" Data=\"" + arrowGeometryPath + "\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\"/></theme:ButtonChrome><ControlTemplate.Triggers><Trigger Property=\"IsMouseOver\" Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderMouseOver\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + mouseOverBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + mouseOverHighlightColor + "\"/><Setter TargetName=\"Arrow\" Property=\"Fill\" Value=\"" + mouseOverArrowColor + "\"/></Trigger><Trigger Property=\"IsChecked\" Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderPressed\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + pressedBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + pressedColor + "\"/><Setter TargetName=\"Arrow\" Property=\"Fill\" Value=\"" + pressedArrowColor + "\"/></Trigger><Trigger Property=\"IsEnabled\" Value=\"false\"><Setter TargetName=\"Arrow\" Property=\"Fill\" Value=\"" + arrowDisabledColor + "\"/></Trigger><Trigger Property=\"IsPressed\"        Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderPressed\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + pressedBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + pressedColor + "\"/><Setter TargetName=\"Arrow\" Property=\"Fill\" Value=\"" + pressedArrowColor + "\"/></Trigger></ControlTemplate.Triggers></ControlTemplate>";

                MemoryStream sr = new MemoryStream(Encoding.ASCII.GetBytes(xaml));
                ParserContext pc = new ParserContext();
                pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
                pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
                pc.XmlnsDictionary.Add("theme", "clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero");
                var btnTemplate = (ControlTemplate)XamlReader.Load(sr, pc);
                x.Template = btnTemplate;
            }
            else
            {
                cmbx.ApplyTemplate();
                Grid tgb = (Grid)cmbx.Template.FindName("Placement", cmbx);
                ToggleButton x = (ToggleButton)tgb.Children[3];

                string xaml = "<ControlTemplate TargetType=\"{x:Type ToggleButton}\"><theme:ButtonChrome Name=\"Chrome\"  Width=\"" + widthOrArrowMargin + "\" Background=\"" + toggleButtonBackground + "\" BorderBrush=\"" + toggleButtonBorderBrush + "\" RenderMouseOver=\"{TemplateBinding IsMouseOver}\" RenderPressed=\"{TemplateBinding IsPressed}\" RoundCorners=\"" + ((roundedCorners) ? "true" : "false") + "\" SnapsToDevicePixels=\"true\"><Path Name=\"Arrow\" Margin=\"0,1,0,0\" Fill=\"" + arrowFillColor + "\" Data=\"" + arrowGeometryPath + "\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\"/></theme:ButtonChrome><ControlTemplate.Triggers><Trigger Property=\"IsMouseOver\" Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderMouseOver\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + mouseOverBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + mouseOverHighlightColor + "\"/><Setter TargetName=\"Arrow\" Property=\"Fill\" Value=\"" + mouseOverArrowColor + "\"/></Trigger><Trigger Property=\"IsChecked\" Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderPressed\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + pressedBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + pressedColor + "\"/><Setter TargetName=\"Arrow\" Property=\"Fill\" Value=\"" + pressedArrowColor + "\"/></Trigger><Trigger Property=\"IsEnabled\" Value=\"false\"><Setter TargetName=\"Arrow\" Property=\"Fill\" Value=\"" + arrowDisabledColor + "\"/></Trigger><Trigger Property=\"IsPressed\"        Value=\"true\"><Setter TargetName=\"Chrome\" Property=\"RenderPressed\" Value=\"false\"/><Setter TargetName=\"Chrome\" Property=\"BorderBrush\" Value=\"" + pressedBorderColor + "\"/><Setter TargetName=\"Chrome\" Property=\"Background\" Value=\"" + pressedColor + "\"/><Setter TargetName=\"Arrow\" Property=\"Fill\" Value=\"" + pressedArrowColor + "\"/></Trigger></ControlTemplate.Triggers></ControlTemplate>";

                MemoryStream sr = new MemoryStream(Encoding.ASCII.GetBytes(xaml));
                ParserContext pc = new ParserContext();
                pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
                pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
                pc.XmlnsDictionary.Add("theme", "clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero");
                var btnTemplate = (ControlTemplate)XamlReader.Load(sr, pc);
                x.Template = btnTemplate;
            }
        }

        #region Core ComboBox-Specific Construction Methods

        public static ComboBox Initialize(this ComboBox source, ContainerType containerType, double scrollViewerHeight, ComboStyles cmbStyles, Brush highlightTextColor, Brush highlightBackgroundColor)
        {
            return Initialize(source, double.NaN, double.NaN, containerType, scrollViewerHeight, cmbStyles, highlightTextColor, highlightBackgroundColor); //Default width and height to Auto by setting to NaN
        }

        public static ComboBox Initialize(this ComboBox source, ContainerType containerType, int? rowSpan, int? colSpan, double scrollViewerHeight, ComboStyles cmbStyles, Brush highlightTextColor, Brush highlightBackgroundColor)
        {
            if (rowSpan != null)
            {
                Grid.SetRowSpan(source, (int)rowSpan);
            }

            if (colSpan != null)
            {
                Grid.SetColumnSpan(source, (int)colSpan);
            }

            return Initialize(source, double.NaN, double.NaN, containerType, scrollViewerHeight, cmbStyles, highlightTextColor, highlightBackgroundColor); //Default width and height to Auto by setting to NaN
        }

        public static ComboBox Initialize(this ComboBox source, double width, double height, ContainerType containerType, int? rowSpan, int? colSpan, double scrollViewerHeight, ComboStyles cmbStyles, Brush highlightTextColor, Brush highlightBackgroundColor)
        {
            if (rowSpan != null)
            {
                Grid.SetRowSpan(source, (int)rowSpan);
            }

            if (colSpan != null)
            {
                Grid.SetColumnSpan(source, (int)colSpan);
            }

            return Initialize(source, width, height, containerType, scrollViewerHeight, cmbStyles, highlightTextColor, highlightBackgroundColor); //Default width and height to Auto by setting to NaN
        }

        public static ComboBox Initialize(this ComboBox source, double width, double height, ContainerType containerType, double scrollViewerHeight, ComboStyles cmbStyles, Brush highlightTextColor, Brush highlightBackgroundColor)
        {
            //Force the Aero theme by default to assure the structure of the ComboBox
            Uri uri = new Uri("/PresentationFramework.Aero;component/themes/Aero.NormalColor.xaml", UriKind.Relative);
            source.Resources.MergedDictionaries.Add(Application.LoadComponent(uri) as ResourceDictionary);

            source.Width = width;
            source.Height = height;

            Style newStyle = new Style(typeof(ComboBoxItem), (Style)source.Resources[typeof(ComboBoxItem)]);
            newStyle.Resources.Add(SystemColors.HighlightTextBrushKey, highlightTextColor);
            newStyle.Resources.Add(SystemColors.HighlightBrushKey, highlightBackgroundColor);
            source.Resources[typeof(ComboBoxItem)] = newStyle;

            if(cmbStyles == ComboStyles.TypeAheadButCannotSelectOrCopyText)
            {
                source.IsTextSearchEnabled = true;
                source.IsEditable = false;
                source.IsReadOnly = true;

                //NOTE: this yields the same behavior as above
                //  source.IsEditable = false;
                //  source.IsReadOnly = false;
            }

            if(cmbStyles == ComboStyles.NoTypeAheadButSelectableText)
            {
                source.IsTextSearchEnabled = false;
                source.IsEditable = true;
                source.IsReadOnly = true;
            }

            if (cmbStyles == ComboStyles.TypeAheadSelectableButAcceptsAnyText)
            {
                source.IsTextSearchEnabled = true;
                source.IsEditable = true;
                source.IsReadOnly = false;
            }
            source.SelectedIndex = -1;
            source.SetValue(TextSearch.TextPathProperty, "ToolTip");

            source.SetContainerType(containerType);
            IComposite icomp = CompositeTypeHelper.CreateIComposite<ComboBox>(source);
            source.SetIComposite<ComboBox>(icomp);

            //STORE SETTING BUILD CHAIN AND GET CHAIN?!?  Put these in a Composite implements an interface
            ComboBoxParent lbsr = new ComboBoxParent();
            source.StoreSetting<ComboBox>("IParent", lbsr);
            source.StoreSetting<ComboBox>("IScrollViewerStrategy", lbsr);

            source.AddItemBorder(Brushes.Gray, new Thickness(0, 0, 0, 1)); //default Border     
            source.StoreSetting<ComboBox>("BorderSettings", new BorderSettings() { Width = double.NaN, Height = double.NaN, BorderBrush = Brushes.Gray, BorderThickness = new Thickness(0, 0, 0, 0), CornerRadius = new CornerRadius(0), Padding = new Thickness(0) });
            setComboBoxItemPaddingToZero(source);

            source.GetScrollViewer<ComboBox>().CanContentScroll = false;
            source.GetScrollViewer<ComboBox>().Height = scrollViewerHeight;

            //source.StoreSetting<ComboBox>("ScrollViewerDeltaStep", 1);
            //source.StoreSetting<ComboBox>("HorizScrollViewerDeltaStep", 1);

            //source.StoreSetting<ComboBox>("ScrollViewerScrollDownStep", 1);
            //source.StoreSetting<ComboBox>("ScrollViewerScrollDownDelay", 1000);
            //source.StoreSetting<ComboBox>("ScrollViewerScrollDownInterval", 100);
            //source.StoreSetting<ComboBox>("ScrollViewerPageDownStep", 1);
            //source.StoreSetting<ComboBox>("ScrollViewerPageDownDelay", 1000);
            //source.StoreSetting<ComboBox>("ScrollViewerPageDownInterval", 100);

            //source.StoreSetting<ComboBox>("ScrollViewerPageUpStep", 1);
            //source.StoreSetting<ComboBox>("ScrollViewerPageUpDelay", 1000);
            //source.StoreSetting<ComboBox>("ScrollViewerPageUpInterval", 100);
            //source.StoreSetting<ComboBox>("ScrollViewerScrollUpStep", 1);
            //source.StoreSetting<ComboBox>("ScrollViewerScrollUpDelay", 1000);
            //source.StoreSetting<ComboBox>("ScrollViewerScrollUpInterval", 100);

            //source.StoreSetting<ComboBox>("ScrollViewerScrollRightStep", 1);
            //source.StoreSetting<ComboBox>("ScrollViewerScrollRightDelay", 1000);
            //source.StoreSetting<ComboBox>("ScrollViewerScrollRightInterval", 100);
            //source.StoreSetting<ComboBox>("ScrollViewerPageRightStep", 1);
            //source.StoreSetting<ComboBox>("ScrollViewerPageRightDelay", 1000);
            //source.StoreSetting<ComboBox>("ScrollViewerPageRightInterval", 100);

            //source.StoreSetting<ComboBox>("ScrollViewerPageLeftStep", 1);
            //source.StoreSetting<ComboBox>("ScrollViewerPageLeftDelay", 1000);
            //source.StoreSetting<ComboBox>("ScrollViewerPageLeftInterval", 100);
            //source.StoreSetting<ComboBox>("ScrollViewerScrollLeftStep", 1);
            //source.StoreSetting<ComboBox>("ScrollViewerScrollLeftDelay", 1000);
            //source.StoreSetting<ComboBox>("ScrollViewerScrollLeftInterval", 100);

            source.StoreSetting<ComboBox>("ObsCol", new ObservableCollection<Border>());

            //ScrollViewerExt.SetVerticalScrollButtonDownHandler(source);
            //ScrollViewerExt.SetVerticalPageButtonDownHandler(source);
            //ScrollViewerExt.SetHorizontalScrollButtonRightHandler(source);
            //ScrollViewerExt.SetHorizontalPageButtonRightHandler(source);

            //ScrollViewerExt.SetVerticalPageButtonUpHandler(source);
            //ScrollViewerExt.SetHorizontalScrollButtonLeftHandler(source);
            //ScrollViewerExt.SetHorizontalPageButtonLeftHandler(source);

            //ScrollViewerExt.SetThumbDragDeltaHandler(source, lbsr);
            //ScrollViewerExt.SetHorizThumbDragDeltaHandler(source, lbsr);

            return source;
        }

        public static void UseWrapPanel(this ComboBox source)
        {
            source.ItemsPanel = new ItemsPanelTemplate(new FrameworkElementFactory(typeof(WrapPanel)));
            source.GetScrollViewer().HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
        }

        public static void UseHorizontalComboBox(this ComboBox source)
        {
            source.ItemsPanel = new ItemsPanelTemplate(new FrameworkElementFactory(typeof(WrapPanel)));
        }

        private static void setComboBoxItemPaddingToZero(ComboBox source)
        {
            Style newStyle = new Style(typeof(ComboBoxItem), (Style)source.Resources[typeof(ComboBoxItem)]);
            Setter setter = new Setter();
            setter.Property = ComboBoxItem.PaddingProperty;
            setter.Value = new Thickness(0);
            newStyle.Setters.Add(setter);
            source.Resources[typeof(ComboBoxItem)] = newStyle;
        }

        #endregion

        #region Store Settings Specific To ComboBox

        public static ComboBox SetMaxRows(this ComboBox chain, int maxRows)
        {
            chain.StoreSetting<ComboBox>("MaxRows", maxRows);
            return chain;
        }

        //public static void SetMouseOverColor(this StackPanel chain, Brush brush)
        //{
        //    int row = 0;
        //    int column = 0;

        //    //Change this to reference ContainerType for maintenance purposes?
        //    if ((((StackPanel)chain).Children[0]) is Grid)
        //    {
        //        Grid g = ((Grid)(((StackPanel)chain).Children[0]));

        //        Style style = new Style(typeof(Grid), g.Style);
        //        Trigger t = new Trigger();
        //        t.Property = Grid.IsMouseOverProperty;
        //        t.Value = true;
        //        Setter setter = new Setter();
        //        setter.Property = Grid.BackgroundProperty;
        //        setter.Value = brush;
        //        t.Setters.Add(setter);

        //        style.Triggers.Add(t); // Important: add a trigger before applying style
        //        g.Style = style;
        //    }
        //    else
        //    {
        //        StackPanel g = ((StackPanel)chain);

        //        Style style = new Style(typeof(StackPanel), g.Style);
        //        Trigger t = new Trigger();
        //        t.Property = StackPanel.IsMouseOverProperty;
        //        t.Value = true;
        //        Setter setter = new Setter();
        //        setter.Property = StackPanel.BackgroundProperty;
        //        setter.Value = brush;
        //        t.Setters.Add(setter);

        //        style.Triggers.Add(t); // Important: add a trigger before applying style
        //        g.Style = style;
        //    }
        //}

        public static ComboBox SetScrollViewerPadding(this ComboBox chain, Thickness padding)
        {
            chain.StoreSetting<ComboBox>("ScrollViewerPadding", padding);
            return chain;
        }

        public static ComboBox SetBackgroundColor(this ComboBox chain, Brush brush)
        {
            Brush newBrush = (brush);
            chain.Background = newBrush;
            return chain;
        }

        public static ComboBox SetBackgroundColorGradient(this ComboBox chain, string gradientStop1Color, double gradientStop1Offset, string gradientStop2Color, double gradientStop2Offset, int startPointX, int startPointY, int endPointX, int endPointY)
        {
            LinearGradientBrush backgroundLinearBrush = BrushExt.CreateGradientBrush(gradientStop1Color, gradientStop1Offset, gradientStop2Color, gradientStop2Offset, startPointX, startPointY, endPointX, endPointY);

            chain.Background = backgroundLinearBrush;
            return chain;
        }

        public static ComboBox SetBackgroundColor(this ComboBox chain, byte red, byte green, byte blue, byte alpha)
        {
            Brush newBrush = (Brush)(new
System.Windows.Media.SolidColorBrush(new System.Windows.Media.Color() { R = red, G = green, B = blue, A = alpha }));
            chain.Background = newBrush;
            return chain;
        }

        public static SettingsChain<ComboBox> SetSelectedContentControlColor(this SettingsChain<ComboBox> chain, Color color)
        {
            ((ComboBox)chain.Item1).SetSelectedContentControlColor(color);

            return chain;
        }

        public static ComboBox SetSelectedContentControlColor(this ComboBox chain, Color color)
        {
            chain.Resources.Add(SystemColors.HighlightBrushKey, new SolidColorBrush(color));
            chain.Resources.Add(SystemColors.ControlBrushKey, new SolidColorBrush(color));
            return chain;
        }

        public static ComboBox SetSelectedContentControlColorGradient(this
ComboBox chain, string gradientStop1Color, double gradientStop1Offset, string gradientStop2Color, double gradientStop2Offset, int startPointX, int startPointY, int endPointX, int endPointY)
        {
            GradientStopCollection gradientStopsLinearBrush = new GradientStopCollection();
            gradientStopsLinearBrush.Add(
                new GradientStop((Color)ColorConverter.ConvertFromString(gradientStop1Color), gradientStop1Offset));
            gradientStopsLinearBrush.Add(
                new GradientStop((Color)ColorConverter.ConvertFromString(gradientStop2Color), gradientStop2Offset));

            chain.Resources.Add(SystemColors.HighlightBrushKey, new LinearGradientBrush(gradientStopsLinearBrush)
            {
                StartPoint = new Point(startPointX, startPointY),
                EndPoint = new Point(endPointX, endPointY)
            });
            chain.Resources.Add(SystemColors.ControlBrushKey, new LinearGradientBrush(gradientStopsLinearBrush)
            {
                StartPoint = new Point(startPointX, startPointY),
                EndPoint = new Point(endPointX, endPointY)
            });

            return chain;
        }

        #endregion
       
        #region Selected Key, Border, and Content Control, and ScrollIntoView

        //Implement an interface for Selected, similar to ScrollViewer?!?

        //public static string SelectedKey(this System.Windows.Controls.SelectionChangedEventArgs selectedArgs)
        //{
        //    //String retVal = String.Empty;
        //    //if (selectedArgs.AddedItems.Count > 0)
        //    //{
        //    //    retVal = selectedArgs.AddedItems[0].Cast<Border>().Child.Cast<ContentControl>().Tag.Cast<ComboBox>().SelectedKey();
        //    //}

        //    return retVal;
        //}

        public static void SetSelectedKey(this ComboBox source, string key)
        {
            System.Collections.Generic.KeyValuePair<string, object> pair = (System.Collections.Generic.KeyValuePair<string, object>)source.GetCompositeLookupDictionary().Where<System.Collections.Generic.KeyValuePair<string, object>>((kvp, i) =>
            {
                if (kvp.Key == key)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }).First();

            if (pair.Value != null)
            {
                //ComboBoxArgs args = source.GetSetting<ComboBox, ComboBoxArgs>("ComboBoxArgs"+key);

                //int searchX = (args as ComboBoxArgs).SearchTextX;
                //int searchY = (args as ComboBoxArgs).SearchTextY;

                if (source.IsEditable == true)
                {
                    source.SelectedItem = ((Border)pair.Value);

                }
                else
                {
                    source.SelectedItem = (Border)pair.Value;
                }
            }
        }

        //public static void ScrollIntoViewByKey(this ComboBox source, string key)
        //{
        //    System.Collections.Generic.KeyValuePair<string, object> pair = (System.Collections.Generic.KeyValuePair<string, object>)source.GetCompositeLookupDictionary().Where<System.Collections.Generic.KeyValuePair<string, object>>((kvp, i) =>
        //    {
        //        if (kvp.Key == key)
        //        {
        //            return true;
        //        }
        //        else
        //        {
        //            return false;
        //        }
        //    }).First();

        //    if (pair.Value != null)
        //    {
        //        source.ScrollIntoView((Border)pair.Value);
        //    }
        //}

        //public static string SelectedKey(this ComboBox source)
        //{
        //    string retVal = null;

        //    Dictionary<string, object> CompositeLookup = CommonExt.GetCompositeLookupDictionaryFromComposite<FrameworkElement>(source.SelectedBorder());

        //    System.Collections.Generic.KeyValuePair<string, object> ibe = CompositeLookup.Where(row =>
        //    {
        //        if (row.Value == source.SelectedBorder()) { return true; } else { return false; }
        //    }).First();

        //    retVal = ibe.Key.ToString();

        //    return retVal;
        //}

        //public static bool StillHasItemSelected(this System.Windows.Controls.SelectionChangedEventArgs eav)
        //{
        //    bool retVal = false;
        //    if (eav.AddedItems.Count > 0)
        //    {
        //        retVal = true;
        //    }

        //    return retVal;
        //}

        public static Border SelectedBorder(this ComboBox source)
        {
            Border returnedObject = null;

            object x = source.SelectedItem;

            if (x != null)
            {
                returnedObject = ((Border)x);
            }

            return returnedObject;
        }

        public static Border SelectedBorder(this System.Windows.Controls.SelectionChangedEventArgs selectedArgs)
        {
            return selectedArgs.AddedItems[0].Cast<Border>();
        }

        public static ContentControl SelectedContentControl(this System.Windows.Controls.SelectionChangedEventArgs selectedArgs)
        {
            return selectedArgs.AddedItems[0].Cast<Border>().Child.Cast<ContentControl>();
        }

        public static ContentControl SelectedContentControl(this ComboBox source)
        {
            ContentControl returnedObject = null;

            object x = source.SelectedItem;

            if (x != null)
            {

                if (x is Border)
                {
                    returnedObject = ((Border)x).Child.Cast<ContentControl>();
                }
                else
                {
                    returnedObject = x.Cast<ContentControl>();
                }
            }

            return returnedObject;
        }

        #endregion

    }//end of class

}//end of namespace
